package com.zh.singletonmode;

import com.zh.singletonmode.services.lazy.*;
import com.zh.singletonmode.services.register.EnumSingleton;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;

public class ModeApplication {
//    public static void main(String[] args) {
//        for (int i = 0; i < 15; i++) {
//            new Thread(() ->{
//                LazySingleton lazySingleton = LazySingleton.getInstance();
//                System.out.println(Thread.currentThread().getName() + "：" + lazySingleton);
//            }).start();
//        }
//    }

//    public static void main(String[] args) {
//        for (int i = 0; i < 15; i++) {
//            new Thread(() ->{
//                SynchronizedLazySingleton synchronizedlazySingleton = SynchronizedLazySingleton.getInstance();
//                System.out.println(Thread.currentThread().getName() + "：" + synchronizedlazySingleton);
//            }).start();
//        }
//    }

//    public static void main(String[] args) {
//        for (int i = 0; i < 15; i++) {
//            new Thread(() ->{
//                InnerClassLazySingleton innerClassLazySingleton = InnerClassLazySingleton.getInstance();
//                System.out.println(Thread.currentThread().getName() + "：" + innerClassLazySingleton);
//            }).start();
//        }
//    }

//    public static void main(String[] args) {
//        //反射破坏单例
//        try {
////            Class<?> cla = InnerClassLazySingleton.class;
//            Class<?> cla = InnerClassLazySingletonCompulsory.class;
//
//            //反射获取私有的构造方法
//            Constructor c = cla.getDeclaredConstructor(null);
//            //强制访问
//            c.setAccessible(true);
//
//            //第一次初始化
//            Object obj1 = c.newInstance();
//            //第二次初始化
//            Object obj2 = c.newInstance();
//
//            System.out.println(obj1);
//            System.out.println(obj2);
//            System.out.println(obj1 == obj2);
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//    }

//    public static void main(String[] args) {
//        //序列化破坏单例
//        try{
//            LazySingletonSerialize instanceOut = LazySingletonSerialize.getInstance();
//
//            //输出流序列化
//            FileOutputStream fos = new FileOutputStream("Serialize.obj");
//            ObjectOutputStream oos = new ObjectOutputStream(fos);
//            oos.writeObject(instanceOut);
//            oos.flush();
//            oos.close();
//
//            LazySingletonSerialize instanceInput = null;
//            //输入流序列化
//            FileInputStream fis = new FileInputStream("Serialize.obj");
//            ObjectInputStream ois = new ObjectInputStream(fis);
//            instanceInput = (LazySingletonSerialize) ois.readObject();
//            ois.close();
//
//            System.out.println(instanceInput);
//            System.out.println(instanceOut);
//            System.out.println(instanceInput == instanceOut);
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//    }

//    public static void main(String[] args) {
//        //枚举单例模式解决反射破坏单例
//        try {
//            Class<?> cla = EnumSingleton.class;
//
//            //反射获取私有的构造方法,因为枚举类没有构造方法，所以这里会抛出异常
//            Constructor c = cla.getDeclaredConstructor(null);
//            //强制访问
//            c.setAccessible(true);
//
//            //初始化
//            Object obj1 = c.newInstance();
//
//            System.out.println(obj1);
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//    }

    public static void main(String[] args) {
        try{
            //枚举单例模式解决序列化破坏单例
            //定义枚举对象，初始化Object，等待输出序列号对象写入
            EnumSingleton instanceOut = EnumSingleton.getInstance();
            instanceOut.setData(new Object());

            //输出流序列化
            FileOutputStream fos = new FileOutputStream("Serialize.obj");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(instanceOut);
            oos.flush();
            oos.close();

            //定义枚举对象，等待赋值输入序列号对象
            EnumSingleton instanceInput = null;

            //输入流序列化
            FileInputStream fis = new FileInputStream("Serialize.obj");
            ObjectInputStream ois = new ObjectInputStream(fis);
            instanceInput = (EnumSingleton) ois.readObject();
            ois.close();

            System.out.println(instanceInput.getData());
            System.out.println(instanceOut.getData());
            System.out.println(instanceInput.getData() == instanceOut.getData());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
